#include "servicecenter.h"

#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QProcess>
#include <QSettings>
#include <QThread>

ServiceCenter::ServiceCenter(QObject *parent)
    : QObject{parent}
{
    //先读取my.cnf配置文件，读取配置文件中的数据地址，判断数据文件夹是否已存在
    QSettings settings(QCoreApplication::applicationDirPath() + "/my.cnf", QSettings::IniFormat);
    QString dataBaseDataDir = settings.value("mysqld/datadir").toString();
    QDir dir(dataBaseDataDir);
    bool isFristRun = false;
    if (!dir.exists())
    {
        isFristRun = true;
        //数据文件夹不存在，说明是第一次运行，需要初始化数据库
        QProcess initProcess;
        QString mysqldPath = QCoreApplication::applicationDirPath() + "/bin/mysqld.exe";
        QStringList initArgs;
        initArgs << "--initialize-insecure"
                 << "--datadir=" + dataBaseDataDir;
        initProcess.start(mysqldPath, initArgs);
        if (!initProcess.waitForStarted(5000))
        {
            qCritical() << "Failed to start mysqld.exe for initialization: " << initProcess.errorString();
        }
        else
        {
            if (initProcess.waitForFinished(30000))
            {
                QString err = QString::fromLocal8Bit(initProcess.readAllStandardError());
                if (!err.isEmpty())
                {
                    qCritical() << "初始化错误：" << err;
                }
                qInfo() << "数据库初始化成功";
            }
            else
            {
                initProcess.kill();
                qCritical() << "初始化超时";
            }
        }
    }

    // 启动 MySQL 服务器
    mysqlProcess = new QProcess(this);
    QString mysqldPath = QCoreApplication::applicationDirPath() + "/bin/mysqld.exe";
    QString defaultsFile = QCoreApplication::applicationDirPath() + "/my.cnf";
    mysqlProcess->setProgram(mysqldPath);

    mysqlProcess->setArguments({"--defaults-file=" + defaultsFile});
    mysqlProcess->start();
    if (!mysqlProcess->waitForStarted(15000))
    {
        qCritical() << "启动 mysqld.exe 失败：" << mysqlProcess->errorString();
    }
    else
    {
        // 3. 等待服务就绪（检测端口监听）
        if (waitForMysqlReady())
        {
            qInfo() << "MySQL 服务启动成功";
            if (isFristRun)
            {
                createRootPassword();
            }
        }
        else
        {
            qCritical() << "服务启动后未就绪，可能启动失败（查看日志确认）";
            mysqlProcess->kill();
        }
    }
}

ServiceCenter::~ServiceCenter()
{
    // 关闭Mysql服务
    QSettings settings(QCoreApplication::applicationDirPath() + "/my.cnf", QSettings::IniFormat);
    QString dataBasePort = settings.value("mysqld/port", 3307).toString();
    QProcess shutdownProcess;
    QString mysqladminPath = QCoreApplication::applicationDirPath() + "/bin/mysqladmin.exe";
    shutdownProcess.setProgram(mysqladminPath);
    QStringList args = {
        "shutdown",
        "-h", "127.0.0.1",
        "-P", dataBasePort,
        "-u", "root"};

    shutdownProcess.setArguments(args);
    shutdownProcess.start();
    if (!shutdownProcess.waitForStarted())
    {
        qCritical() << "Failed to start mysqladmin for shutdown: " << shutdownProcess.errorString();
    }
    else
    {
        if (shutdownProcess.waitForFinished(15000))
        {
            QString err = QString::fromLocal8Bit(shutdownProcess.readAllStandardError());
            if (err.isEmpty())
            {
                qInfo() << "MySQL 服务关闭成功";
                mysqlProcess->waitForFinished();
            }
            else
            {
                qCritical() << "关闭失败: " << err;
                if (mysqlProcess->state() == QProcess::Running)
                {
                    mysqlProcess->kill();
                    mysqlProcess->waitForFinished();
                    qInfo() << "强制关闭 MySQL 服务";
                }
            }
        }
        else
        {
            shutdownProcess.kill();
            qCritical() << "关闭超时，强制终止服务";
            if (mysqlProcess->state() == QProcess::Running)
            {
                mysqlProcess->kill();
                mysqlProcess->waitForFinished();
            }
        }
    }
}

bool ServiceCenter::waitForMysqlReady()
{
    QSettings settings(QCoreApplication::applicationDirPath() + "/my.cnf", QSettings::IniFormat);
    QString dataBasePort = settings.value("mysqld/port").toString();
    QString mysqladminPath = QCoreApplication::applicationDirPath() + "/bin/mysqladmin.exe";
    // 先检查 mysqladmin 工具是否存在
    if (!QFile::exists(mysqladminPath))
    {
        qCritical() << "mysqladmin.exe 不存在：" << mysqladminPath;
        return false;
    }

    // 最多等 10次，每秒检查一次
    for (int i = 0; i < 10; ++i)
    {
        QProcess pingProcess;
        pingProcess.setProgram(mysqladminPath);
        QStringList args = {
            "ping",
            "-h", "127.0.0.1",
            "-P", dataBasePort,
            "-u", "root",
            "--password="}; // 空密码
        pingProcess.setArguments(args);
        pingProcess.start();
        if (pingProcess.waitForFinished(1000))
        {
            if (pingProcess.exitCode() == 0)
            {
                return true;
            }
        }
        pingProcess.kill();
        QThread::msleep(500); // 间隔500ms再检测，避免频繁占用资源
    }
    return false;
}

void ServiceCenter::createRootPassword()
{
    // 通过 mysql 客户端执行 SQL 修改密码
    QProcess setPwdProcess;
    QString mysqlPath = QCoreApplication::applicationDirPath() + "/bin/mysql.exe";
    QSettings settings(QCoreApplication::applicationDirPath() + "/my.cnf", QSettings::IniFormat);
    QString dataBasePort = settings.value("mysqld/port").toString();

    QSettings passwordSettings(QCoreApplication::applicationDirPath() + "/fristcreate.ini", QSettings::IniFormat);
    QString initPassword = passwordSettings.value("init/password", "sanshi522").toString();

    // 修改本地密码
    QString createLocalHostUserSql = QString("ALTER USER 'root'@'localhost' IDENTIFIED BY '%1';").arg(initPassword);

    // 额外执行（按需添加）
    QString createAllHostUserSql = QString(
                                       "CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '%1';"
                                       "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;"
                                       "FLUSH PRIVILEGES;")
                                       .arg(initPassword);

    QStringList args;
    args << "-h"
         << "127.0.0.1"
         << "-P" << dataBasePort
         << "-u"
         << "root"
         << "-e" << createAllHostUserSql;

    setPwdProcess.setProgram(mysqlPath);
    setPwdProcess.setArguments(args);
    setPwdProcess.start();

    if (setPwdProcess.waitForFinished(5000))
    {
        QString err = QString::fromLocal8Bit(setPwdProcess.readAllStandardError());
        if (err.isEmpty())
        {
            qInfo() << "root 密码设置成功";
        }
        else
        {
            qCritical() << "设置 root 密码失败：" << err;
        }
    }
    else
    {
        setPwdProcess.kill();
        qCritical() << "设置 root 密码超时";
    }
}
